#ifndef CONTEXT_H
#define CONTEXT_H
#include <string>
#include <list>
#include "AutoPointer.h"
#include "CopyPointer.h"

namespace TreeExpression {
class Expression;
}

class Definition {
	public:
		Definition(const std::string&, const AutoPointer<TreeExpression::Expression>&);

		std::string getName() const;
		AutoPointer<TreeExpression::Expression> getData() const;
		void setData(const AutoPointer<TreeExpression::Expression>&);

	private:
		std::string name;
		AutoPointer<TreeExpression::Expression> data;
};

class Context {
public:
	Context(const std::string&);
	Context(Context*, const std::string&);
	virtual ~Context();

	AutoPointer<TreeExpression::Expression> searchValueDefinitionInContext(const std::string&) const;
	AutoPointer<TreeExpression::Expression> searchValueDefinitionInGlobal(const std::string&) const;
	AutoPointer<TreeExpression::Expression> searchReferenceDefinitionInContext(const std::string&) const;
	AutoPointer<TreeExpression::Expression> searchReferenceDefinitionInGlobal(const std::string&) const;
	std::list< AutoPointer<TreeExpression::Expression> > searchDeclarationInContext(const std::string&) const;
	std::list< AutoPointer<TreeExpression::Expression> > searchDeclarationInGlobal(const std::string&) const;

	void addDefinition(const std::string&, const AutoPointer<TreeExpression::Expression>&);
	void addDefinitionInContext(const std::string&, const AutoPointer<TreeExpression::Expression>&);
	void addDeclaration(const std::string&, const AutoPointer<TreeExpression::Expression>&);

	void setBase(Context*);
	Context join(const Context&) const;

protected:
	std::list< AutoPointer<TreeExpression::Expression> > searchDeclarationInGlobal(const std::string&, std::list< AutoPointer<TreeExpression::Expression> >&) const;
	bool _addDefinition(const std::string&, const AutoPointer<TreeExpression::Expression>&);

private:
	Context* base;
	std::list< Definition > listDefinition;
	std::list< Definition > listDeclaration;
	std::string name;
};

void registerFunction(Context*);

#endif

